#pragma once

#include <unordered_map>
#include <mutex>
#include <memory>

#include "asynclogger.hpp"

namespace Log
{
    class LoggerMgr
    {
    public:

        static LoggerMgr& Instance()
        {
            static LoggerMgr instance;
            return instance;
        }

        bool Exists(const std::string& name)
        {
            {
                std::unique_lock<std::mutex> lock(mtx_);
                auto it = loggers_.find(name);
                if (loggers_.end() == it)
                    return false;

                return true;
            }
        }

        void AddLogger(const AsyncLoggerPtr&& logger)
        {
            if (Exists(logger->Name()))
                return ;
            
            {
                std::unique_lock<std::mutex> lock(mtx_);
                loggers_.insert(std::make_pair(logger->Name(), logger));
            }
        }

        inline AsyncLoggerPtr GetLogger(const std::string& name)
        {
            std::unique_lock<std::mutex> lock(mtx_);
            auto it = loggers_.find(name);
            if (it == loggers_.end())
                return nullptr;
            
            return it->second;
        }

        void RemoveLogger(const std::string& name)
        {
            std::unique_lock<std::mutex> lock(mtx_);
            auto it = loggers_.find(name);
            if (it != loggers_.end())
                loggers_.erase(it);
        }

        AsyncLoggerPtr DefaultLogger() const
        {            
            return default_logger_;
        }

    private:
        std::mutex mtx_;
        std::unordered_map<std::string, AsyncLoggerPtr> loggers_;
        AsyncLoggerPtr default_logger_;
    };
}